package java5.io;

public class RecursivoLoser implements Constantes {

    private UtilLoser util;
    private CalculoLoser calculo;
    private int[] amenazasrival;
    private int[][] capturas;

    public RecursivoLoser(UtilLoser util, CalculoLoser calculo) {
        this.util = util;
        this.calculo = calculo;
        amenazasrival = new int[100];
        capturas = new int[50][4];
    }

    public int[][] devolverJugadas(int[] tablero, int jugador, int rival, int[] jugada, int[] opc, int[] opc_rival) {
        int[][] jugadas;
        int[][] amenazasescondidas;
        int pos_king;
        int pos_jaque;

        pos_king = util.devuelvePosicionRey(tablero, jugador);

        pos_jaque = this.devolverCasillasAmenazadas(tablero, amenazasrival, rival, pos_king, opc_rival);
        amenazasescondidas = calculo.devolverCasillasAmenazadasEscondidas(tablero,
                rival, jugador, jugada[1], jugada[2], pos_king, opc_rival, opc);

        if (pos_jaque != -1) {//si hay jaque
            jugadas = calculo.buscarJugadasenJaque(tablero, amenazasrival, jugador,
                    jugada[1], jugada[2], amenazasescondidas, pos_king, pos_jaque, rival, opc, opc_rival);
            if (jugadas[_cabeceraJugadas][_tieneJugadasObligatorias] == 1) {
                jugadas = util.ordenarCapturas(jugadas, amenazasrival);
            } else if (jugadas[_cabeceraJugadas][_hayJaque] == 1) {
                jugadas = util.ordenarJaque(jugadas, tablero, jugador);
            }

        } else {
            int[][] cap = this.devolverCapturas(tablero, jugador, jugada, amenazasrival, amenazasescondidas, opc);

            if (cap[0][0] > 1) {
                cap[_cabeceraJugadas][_tieneJugadasObligatorias] = 1;
                jugadas = util.ordenarCapturas(cap, amenazasrival);
            } else {
                jugadas = new int[][]{cap[0]};
            }
        }

        return jugadas;
    }

    public int[][] devolverCapturas(int[] tablero, int color, int[] j, int[] amenazas,
            int[][] escondidas, int[] opc) {

        int c = 1;
        int[] esc;
        int ficha;

        util.iniciarCabeceraJugada(capturas[0]);

        for (int i = 0; i < 64; i++) {
            ficha = tablero[i];

            if (ficha * color > 0) {
                esc = util.buscarIndiceAmenazaEscondida(escondidas, i);
                if (esc != null && esc[sinMovimientos] == 1) {
                    continue;
                }

                switch (ficha) {
                    case PAWN:
                    case pawn:
                        switch (color) {
                            case white:
                                if (i % 8 != 0 && (esc == null || esc[diagonalSuperiorIzquierda] == 1)) {
                                    if (tablero[i + 7] != vacio) {
                                        if (tablero[i + 7] > vacio) {
                                            if (i + 7 > 55 && i + 7 < 64) {
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 7, QUEEN);
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 7, ROOK);
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 7, BISHOP);
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 7, KNIGHT);
                                            } else {
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 7, 0);
                                            }
                                        }
                                    } else if (j[0] == pawn) {
                                        if (j[1] >= 48 && j[1] <= 55 && j[2] == j[1] - 16 && j[2] == i - 1) {
                                            this.ingresarJugada(capturas[c++], PAWN, i, i + 7, 0);
                                        }
                                    }
                                }
                                if ((i + 1) % 8 != 0 && (esc == null || esc[diagonalSuperiorDerecha] == 1)) {
                                    if (tablero[i + 9] != vacio) {
                                        if (tablero[i + 9] > vacio) {
                                            if (i + 9 > 55 && i + 9 < 64) {
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 9, QUEEN);
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 9, ROOK);
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 9, BISHOP);
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 9, KNIGHT);
                                            } else {
                                                this.ingresarJugada(capturas[c++], PAWN, i, i + 9, 0);
                                            }
                                        }
                                    } else if (j[0] == pawn) {
                                        if (j[1] >= 48 && j[1] <= 55 && j[2] == j[1] - 16 && j[2] == i + 1) {
                                            this.ingresarJugada(capturas[c++], PAWN, i, i + 9, 0);
                                        }
                                    }
                                }
                                break;
                            case black:
                                if ((i + 1) % 8 != 0 && (esc == null || esc[diagonalInferiorDerecha] == 1)) {
                                    if (tablero[i - 7] != vacio) {
                                        if (tablero[i - 7] < vacio) {
                                            if (i - 7 > 0 && i - 7 < 8) {
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 7, queen);
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 7, rook);
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 7, bishop);
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 7, knight);
                                            } else {
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 7, 0);
                                            }
                                        }
                                    } else if (j[0] == PAWN) {
                                        if (j[1] >= 8 && j[1] <= 15 && j[2] == j[1] + 16 && j[2] == i + 1) {
                                            this.ingresarJugada(capturas[c++], pawn, i, i - 7, 0);
                                        }
                                    }
                                }
                                if (i % 8 != 0 && (esc == null || esc[diagonalInferiorIzquierda] == 1)) {
                                    if (tablero[i - 9] != vacio) {
                                        if (tablero[i - 9] < vacio) {
                                            if (i - 9 >= 0 && i - 9 < 8) {
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 9, queen);
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 9, rook);
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 9, bishop);
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 9, knight);
                                            } else {
                                                this.ingresarJugada(capturas[c++], pawn, i, i - 9, 0);
                                            }
                                        }
                                    } else if (j[0] == PAWN) {
                                        if (j[1] >= 8 && j[1] <= 15 && j[2] == j[1] + 16 && j[2] == i - 1) {
                                            this.ingresarJugada(capturas[c++], pawn, i, i - 9, 0);
                                        }
                                    }
                                }
                                break;
                        }
                        capturas[0][0] = c;
                        break;
                    case KNIGHT:
                    case knight:
                        //+6 -6
                        if (i < 56 && i % 8 > 1) {
                            if (tablero[i + 6] * color < 0) {
                                this.ingresarJugada(capturas[c++], opc[1], i, i + 6, 0);
                            }
                        }
                        if (i > 7 && i % 8 < 6) {
                            if (tablero[i - 6] * color < 0) {
                                this.ingresarJugada(capturas[c++], opc[1], i, i - 6, 0);
                            }
                        }
                        //+10 -10
                        if (i < 56 && i % 8 < 6) {
                            if (tablero[i + 10] * color < 0) {
                                this.ingresarJugada(capturas[c++], opc[1], i, i + 10, 0);
                            }
                        }
                        if (i > 7 && i % 8 > 1) {
                            if (tablero[i - 10] * color < 0) {
                                this.ingresarJugada(capturas[c++], opc[1], i, i - 10, 0);
                            }
                        }
                        //+15 -15
                        if (i < 48 && i % 8 > 0) {
                            if (tablero[i + 15] * color < 0) {
                                this.ingresarJugada(capturas[c++], opc[1], i, i + 15, 0);
                            }
                        }
                        if (i > 15 && i % 8 < 7) {
                            if (tablero[i - 15] * color < 0) {
                                this.ingresarJugada(capturas[c++], opc[1], i, i - 15, 0);
                            }
                        }
                        //+17 -17
                        if (i < 48 && i % 8 < 7) {
                            if (tablero[i + 17] * color < 0) {
                                this.ingresarJugada(capturas[c++], opc[1], i, i + 17, 0);
                            }
                        }
                        if (i > 15 && i % 8 > 0) {
                            if (tablero[i - 17] * color < 0) {
                                this.ingresarJugada(capturas[c++], opc[1], i, i - 17, 0);
                            }
                        }
                        capturas[0][0] = c;
                        break;
                    case BISHOP:
                    case bishop:
                        this.buscarCapturasDiagonal(tablero, i, color, true, capturas, opc[2], null, esc);
                        c = capturas[0][0];
                        break;
                    case ROOK:
                    case rook:
                        this.buscarCapturasHorizontalVertical(tablero, i, color, true, capturas, opc[3], null, esc);
                        c = capturas[0][0];
                        break;
                    case QUEEN:
                    case queen:
                        this.buscarCapturasDiagonal(tablero, i, color, true, capturas, opc[4], null, esc);
                        this.buscarCapturasHorizontalVertical(tablero, i, color, true, capturas, opc[4], null, esc);
                        c = capturas[0][0];
                        break;
                    case KING:
                    case king:
                        this.buscarCapturasDiagonal(tablero, i, color, false, capturas, opc[5], amenazas, esc);
                        this.buscarCapturasHorizontalVertical(tablero, i, color, false, capturas, opc[5], amenazas, esc);
                        c = capturas[0][0];
                        break;
                }
            }
        }

        return capturas;
    }

    private void buscarCapturasDiagonal(int[] tablero, int pos, int color, boolean esRecursivo,
            int[][] capturas, int pieza, int[] amenazas, int[] esc) {

        int factor = 1;
        int val;
        int c = capturas[0][0];
        boolean a7 = true,
                b7 = true,
                a9 = true,
                b9 = true;

        do {
            if (a7) {
                val = pos - (7 * factor);
                if (val % 8 > 0 && (esc == null || esc[diagonalInferiorDerecha] == 1)) {
                    if (tablero[val] != vacio) {
                        if (tablero[val] * color < 0) {
                            if (!esRecursivo) {
                                if (!util.siArrayContiene(amenazas, val)) {
                                    this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                                }
                            } else {
                                this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                            }
                        }
                        a7 = false;
                    }
                } else {
                    a7 = false;
                }
            }
            if (b7) {
                val = pos + (7 * factor);
                if (val < 64 && val % 8 < 7 && (esc == null || esc[diagonalSuperiorIzquierda] == 1)) {
                    if (tablero[val] != vacio) {
                        if (tablero[val] * color < 0) {
                            if (!esRecursivo) {
                                if (!util.siArrayContiene(amenazas, val)) {
                                    this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                                }
                            } else {
                                this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                            }
                        }
                        b7 = false;
                    }
                } else {
                    b7 = false;
                }
            }
            if (a9) {
                val = pos - (9 * factor);
                if (val >= 0 && val % 8 < 7 && (esc == null || esc[diagonalInferiorIzquierda] == 1)) {
                    if (tablero[val] != vacio) {
                        if (tablero[val] * color < 0) {
                            if (!esRecursivo) {
                                if (!util.siArrayContiene(amenazas, val)) {
                                    this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                                }
                            } else {
                                this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                            }
                        }
                        a9 = false;
                    }
                } else {
                    a9 = false;
                }
            }
            if (b9) {
                val = pos + (9 * factor);
                if (val < 64 && val % 8 > 0 && (esc == null || esc[diagonalSuperiorDerecha] == 1)) {
                    if (tablero[val] != vacio) {
                        if (tablero[val] * color < 0) {
                            if (!esRecursivo) {
                                if (!util.siArrayContiene(amenazas, val)) {
                                    this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                                }
                            } else {
                                this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                            }
                        }
                        b9 = false;
                    }
                } else {
                    b9 = false;
                }
            }
            factor++;
        } while ((a7 || b7 || a9 || b9) && factor < 8 && esRecursivo);

        capturas[0][0] = c;
    }

    private void buscarCapturasHorizontalVertical(int[] tablero, int pos, int color,
            boolean esRecursivo, int[][] capturas, int pieza, int[] amenazas, int[] esc) {
        int factor = 1;
        int val;
        int c = capturas[0][0];
        boolean a1 = true,
                b1 = true,
                a8 = true,
                b8 = true;
        do {
            if (a1) {
                val = pos - (1 * factor);
                if (val >= 0 && val % 8 < 7 && (esc == null || esc[horizontalIzquierda] == 1)) {
                    if (tablero[val] != vacio) {
                        if (tablero[val] * color < 0) {
                            if (!esRecursivo) {
                                if (!util.siArrayContiene(amenazas, val)) {
                                    this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                                }
                            } else {
                                this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                            }
                        }
                        a1 = false;
                    }
                } else {
                    a1 = false;
                }
            }
            if (b1) {
                val = pos + (1 * factor);
                if (val % 8 > 0 && (esc == null || esc[horizontalDerecha] == 1)) {
                    if (tablero[val] != vacio) {
                        if (tablero[val] * color < 0) {
                            if (!esRecursivo) {
                                if (!util.siArrayContiene(amenazas, val)) {
                                    this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                                }
                            } else {
                                this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                            }
                        }
                        b1 = false;
                    }
                } else {
                    b1 = false;
                }
            }
            if (a8) {
                val = pos - (8 * factor);
                if (val >= 0 && (esc == null || esc[verticalInferior] == 1)) {
                    if (tablero[val] != vacio) {
                        if (tablero[val] * color < 0) {
                            if (!esRecursivo) {
                                if (!util.siArrayContiene(amenazas, val)) {
                                    this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                                }
                            } else {
                                this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                            }
                        }
                        a8 = false;
                    }
                } else {
                    a8 = false;
                }
            }
            if (b8) {
                val = pos + (8 * factor);
                if (val < 64 && (esc == null || esc[verticalSuperior] == 1)) {
                    if (tablero[val] != vacio) {
                        if (tablero[val] * color < 0) {
                            if (!esRecursivo) {
                                if (!util.siArrayContiene(amenazas, val)) {
                                    this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                                }
                            } else {
                                this.ingresarJugada(capturas[c++], pieza, pos, val, 0);
                            }
                        }
                        b8 = false;
                    }
                } else {
                    b8 = false;
                }
            }
            factor++;
        } while ((a1 || b1 || a8 || b8) && factor < 8 && esRecursivo);

        capturas[0][0] = c;
    }

    public int devolverCasillasAmenazadas(int[] tablero, int[] amenazas, int color, int pos_king, int[] opc) {

        int pos_jaque = -1;
        int ficha;
        int c = 1;

        amenazas[0] = 0;

        for (int i = 0; i < 64; i++) {
            ficha = tablero[i];

            if (ficha * color > 0) {
                if (ficha == opc[0]) {
                    switch (color) {
                        case white:
                            if (i % 8 != 0) {
                                if (i + 7 == pos_king) {
                                    pos_jaque = pos_jaque == -1 ? i : 100;
                                } else {
                                    amenazas[c++] = i + 7;
                                }
                            }
                            if ((i + 1) % 8 != 0) {
                                if (i + 9 == pos_king) {
                                    pos_jaque = pos_jaque == -1 ? i : 100;
                                } else {
                                    amenazas[c++] = i + 9;
                                }
                            }
                            break;
                        case black:
                            if ((i + 1) % 8 != 0) {
                                if (i - 7 == pos_king) {
                                    pos_jaque = pos_jaque == -1 ? i : 100;
                                } else {
                                    amenazas[c++] = i - 7;
                                }
                            }
                            if (i % 8 != 0) {
                                if (i - 9 == pos_king) {
                                    pos_jaque = pos_jaque == -1 ? i : 100;
                                } else {
                                    amenazas[c++] = i - 9;
                                }
                            }
                            break;
                    }
                } else if (ficha == opc[1]) {
                    //+6 -6
                    if ((i < 56 && i % 8 > 1)) {
                        if (i + 6 == pos_king) {
                            pos_jaque = pos_jaque == -1 ? i : 100;
                        } else {
                            amenazas[c++] = i + 6;
                        }
                    }
                    if (i > 7 && i % 8 < 6) {
                        if (i - 6 == pos_king) {
                            pos_jaque = pos_jaque == -1 ? i : 100;
                        } else {
                            amenazas[c++] = i - 6;
                        }
                    }
                    //+10 -10
                    if (i < 56 && i % 8 < 6) {
                        if (i + 10 == pos_king) {
                            pos_jaque = pos_jaque == -1 ? i : 100;
                        } else {
                            amenazas[c++] = i + 10;
                        }
                    }
                    if (i > 7 && i % 8 > 1) {
                        if (i - 10 == pos_king) {
                            pos_jaque = pos_jaque == -1 ? i : 100;
                        } else {
                            amenazas[c++] = i - 10;
                        }
                    }
                    //+15 -15
                    if (i < 48 && i % 8 > 0) {
                        if (i + 15 == pos_king) {
                            pos_jaque = pos_jaque == -1 ? i : 100;
                        } else {
                            amenazas[c++] = i + 15;
                        }
                    }
                    if (i > 15 && i % 8 < 7) {
                        if (i - 15 == pos_king) {
                            pos_jaque = pos_jaque == -1 ? i : 100;
                        } else {
                            amenazas[c++] = i - 15;
                        }
                    }
                    //+17 -17
                    if (i < 48 && i % 8 < 7) {
                        if (i + 17 == pos_king) {
                            pos_jaque = pos_jaque == -1 ? i : 100;
                        } else {
                            amenazas[c++] = i + 17;
                        }
                    }
                    if ((i > 15 && i % 8 > 0)) {
                        if (i - 17 == pos_king) {
                            pos_jaque = pos_jaque == -1 ? i : 100;
                        } else {
                            amenazas[c++] = i - 17;
                        }
                    }
                } else if (ficha == opc[2]) {
                    pos_jaque = this.buscarAmenazasDiagonal(tablero, i, true, amenazas, pos_king, pos_jaque, c);
                    c = amenazas[0];
                } else if (ficha == opc[3]) {
                    pos_jaque = this.buscarAmenazasHorizontalVertical(tablero, i, true, amenazas, pos_king, pos_jaque, c);
                    c = amenazas[0];
                } else if (ficha == opc[4]) {
                    pos_jaque = this.buscarAmenazasDiagonal(tablero, i, true, amenazas, pos_king, pos_jaque, c);
                    pos_jaque = this.buscarAmenazasHorizontalVertical(tablero, i, true, amenazas, pos_king, pos_jaque, amenazas[0]);
                    c = amenazas[0];
                } else if (ficha == opc[5]) {
                    this.buscarAmenazasDiagonal(tablero, i, false, amenazas, pos_king, pos_jaque, c);
                    this.buscarAmenazasHorizontalVertical(tablero, i, false, amenazas, pos_king, pos_jaque, amenazas[0]);
                    c = amenazas[0];
                }
            }
        }

        amenazas[0] = c;

        return pos_jaque;
    }

    private int buscarAmenazasDiagonal(int[] tablero, int pos, boolean esRecursivo,
            int[] amenazas, int pos_king, int jaque, int c) {
        int pos_jaque = jaque;
        int factor = 1;
        int val;
        boolean a7 = true,
                b7 = true,
                a9 = true,
                b9 = true;
        do {
            if (a7) {
                val = pos - (7 * factor);
                if (val % 8 > 0) {
                    if (tablero[val] != vacio && val != pos_king) {
                        a7 = false;
                    }
                    if (val == pos_king) {
                        pos_jaque = pos_jaque == -1 ? pos : 100;
                    } else {
                        amenazas[c++] = val;
                    }
                } else {
                    a7 = false;
                }
            }
            if (b7) {
                val = pos + (7 * factor);
                if (val < 64 && val % 8 < 7) {
                    if (tablero[val] != vacio && val != pos_king) {
                        b7 = false;
                    }
                    if (val == pos_king) {
                        pos_jaque = pos_jaque == -1 ? pos : 100;
                    } else {
                        amenazas[c++] = val;
                    }
                } else {
                    b7 = false;
                }
            }
            if (a9) {
                val = pos - (9 * factor);
                if (val >= 0 && val % 8 < 7) {
                    if (tablero[val] != vacio && val != pos_king) {
                        a9 = false;
                    }
                    if (val == pos_king) {
                        pos_jaque = pos_jaque == -1 ? pos : 100;
                    } else {
                        amenazas[c++] = val;
                    }
                } else {
                    a9 = false;
                }
            }
            if (b9) {
                val = pos + (9 * factor);
                if (val < 64 && val % 8 > 0) {
                    if (tablero[val] != vacio && val != pos_king) {
                        b9 = false;
                    }
                    if (val == pos_king) {
                        pos_jaque = pos_jaque == -1 ? pos : 100;
                    } else {
                        amenazas[c++] = val;
                    }
                } else {
                    b9 = false;
                }
            }
            factor++;
        } while ((a7 || b7 || a9 || b9) && factor < 8 && esRecursivo);

        amenazas[0] = c;

        return pos_jaque;
    }

    private int buscarAmenazasHorizontalVertical(int[] tablero, int pos,
            boolean esRecursivo, int[] amenazas, int pos_king, int jaque, int c) {
        int pos_jaque = jaque;
        int factor = 1;
        int val;
        boolean a1 = true,
                b1 = true,
                a8 = true,
                b8 = true;
        do {
            if (a1) {
                val = pos - (1 * factor);
                if (val >= 0 && val % 8 < 7) {
                    if (tablero[val] != vacio && val != pos_king) {
                        a1 = false;
                    }
                    if (val == pos_king) {
                        pos_jaque = pos_jaque == -1 ? pos : 100;
                    } else {
                        amenazas[c++] = val;
                    }
                } else {
                    a1 = false;
                }
            }
            if (b1) {
                val = pos + (1 * factor);
                if (val % 8 > 0) {
                    if (tablero[val] != vacio && val != pos_king) {
                        b1 = false;
                    }
                    if (val == pos_king) {
                        pos_jaque = pos_jaque == -1 ? pos : 100;
                    } else {
                        amenazas[c++] = val;
                    }
                } else {
                    b1 = false;
                }
            }
            if (a8) {
                val = pos - (8 * factor);
                if (val >= 0) {
                    if (tablero[val] != vacio && val != pos_king) {
                        a8 = false;
                    }
                    if (val == pos_king) {
                        pos_jaque = pos_jaque == -1 ? pos : 100;
                    } else {
                        amenazas[c++] = val;
                    }
                } else {
                    a8 = false;
                }
            }
            if (b8) {
                val = pos + (8 * factor);
                if (val < 64) {
                    if (tablero[val] != vacio && val != pos_king) {
                        b8 = false;
                    }
                    if (val == pos_king) {
                        pos_jaque = pos_jaque == -1 ? pos : 100;
                    } else {
                        amenazas[c++] = val;
                    }
                } else {
                    b8 = false;
                }
            }
            factor++;
        } while ((a1 || b1 || a8 || b8) && factor < 8 && esRecursivo);

        amenazas[0] = c;

        return pos_jaque;
    }

    private void ingresarJugada(int[] j, int ficha, int ini, int fin, int prom) {
        j[0] = ficha;
        j[1] = ini;
        j[2] = fin;
        j[3] = prom;
    }
}
